#! /bin/bash  
  
Usage()  
{  
    echo "Usage: ${0##*/} [option] [path] search-content"  
    echo "  -S,--string           search string"  
    echo "  -m,--macro            search macro define"  
    echo "  -t,--typedef          search typedef statement"  
    echo "  -c,--class            search class declare"  
    echo "  -s,--struct           search class declare"  
    echo "  -e,--extended-regexp  support grep extended regular expression"  
    echo "  -i,--ignore-case      ignore search-content case"  
    echo "  -h,--help             display help information"  
    echo "[Note]: If you don't specify path, default searching from current directory."  
}  
  
if [ $# -eq 0 ]; then  
  Usage  
  exit 1  
fi  
  
while [ $# -gt 0 ]; do  
    case $1 in  
    -*)  
        case $1 in  
        -S|--string) # this is the default option if you don't specify any option  
            SEARCH_TYPE="string";;  
        -m|--macro)  
            SEARCH_TYPE="macro";;  
        -t|--typedef)  
            SEARCH_TYPE="typedef";;  
        -c|--class)  
            SEARCH_TYPE="class";;  
        -s|--struct)  
            SEARCH_TYPE="struct";;  
        -E|--extended-regexp)  
            GREP_EXT_REG_OPTION="-E";;  
        -i|--ignore-case)  
            GREP_IGNORE_CASE_OPTION="-i";;  
        -h|--help)  
            Usage  
            exit 0;;  
        *)  
            echo "Invalid usage: unknown option $1!"  
            exit 1;;  
        esac ;;  
    *)  
        if [ -d "$1" ]; then  
            if [ -z "$SEARCH_PATH" ]; then  
                SEARCH_PATH="$1"  
            elif [ -z "$SEARCH_CONTENT" ]; then  
                SEARCH_CONTENT="$1"  
            else  
                echo "Invalid usage: too many directory parameters!"  
                exit 1  
            fi  
        elif [ -z "$SEARCH_CONTENT" ]; then  
            SEARCH_CONTENT="$1"  
        else  
            echo "Invalid usage: too many search-content parameters!"  
            exit 1  
        fi ;;  
    esac  
    shift  
done  
  
GREP_EXTRAL_OPTION="-n -H --color $GREP_EXT_REG_OPTION $GREP_IGNORE_CASE_OPTION"  
  
if [ -z $SEARCH_TYPE ]; then  
    SEARCH_TYPE="string"  
fi  
    
if [ -z "$SEARCH_CONTENT" ]; then  
    # perhaps the content to be searched is a path-style name, and not specify path parameter  
    if [ -n "$SEARCH_PATH" ]; then  
        SEARCH_CONTENT="$SEARCH_PATH"  
        SEARCH_PATH="."  
    else  
        echo "Invalid usage: no search-content parameter!"  
        exit 1  
    fi  
fi  
  
if [ -z "$SEARCH_PATH" ]; then  
    SEARCH_PATH="."  
fi  
  
SearchString()  
{  
    for file in `ls`; do  
        if [ "$file" = "." -o "$file" = ".." ]; then  
            continue  
        fi  
        if [ -d $file ]; then  
            cd ./$file # add "./" for those special directories whose name begin with "-"  
            SearchString  
            cd ..  
            continue  
        fi  
        if grep $GREP_EXTRAL_OPTION "$SEARCH_CONTENT" "`pwd`/$file" ; then  
            let "SEARCH_MATCH_COUNT+=1"  
        fi  
    done  
}  
  
Search()  
{  
    for file in `ls`; do  
        if [ "$file" = "." -o "$file" = ".." ]; then  
            continue  
        fi  
        if [ -d $file ]; then  
            cd $file  
            Search  
            cd ..  
            continue  
        fi  
          
        case $SEARCH_TYPE in  
        macro)  
            if grep $GREP_EXTRAL_OPTION "#[[:space:]]*define[[:space:]]*$SEARCH_CONTENT" "`pwd`/$file" ; then  
                let "SEARCH_MATCH_COUNT+=1"  
            fi;;  
        typedef)  
            if grep $GREP_EXTRAL_OPTION "typedef.*$SEARCH_CONTENT" "`pwd`/$file" ; then  
                let "SEARCH_MATCH_COUNT+=1"  
            fi;;  
        class)  
            if grep $GREP_EXTRAL_OPTION "class.*$SEARCH_CONTENT" "`pwd`/$file" ; then  
                let "SEARCH_MATCH_COUNT+=1"  
            fi;;  
        struct)  
            if grep $GREP_EXTRAL_OPTION "struct.*$SEARCH_CONTENT" "`pwd`/$file" ; then  
                let "SEARCH_MATCH_COUNT+=1"  
            fi;;  
        *)  
            if grep $GREP_EXTRAL_OPTION "$SEARCH_CONTENT" "`pwd`/$file" ; then  
                let "SEARCH_MATCH_COUNT+=1"  
            fi;;  
        esac  
    done  
}  
  
pushd $SEARCH_PATH > /dev/null  
SEARCH_MATCH_COUNT=0  
if [ "$SEARCH_TYPE" = "string" ]; then  
    SearchString  
else  
    Search  
fi  
if [ $SEARCH_MATCH_COUNT -lt 1 ]; then  
    echo -e "No $SEARCH_TYPE matches \033[40;31m$SEARCH_CONTENT\033[0m in \033[40;31m$SEARCH_PATH\033[0m directory and its sub-directory!"  
fi  
popd > /dev/null  
